//
// MPaster.java
//
package com.photoexpert;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;

class MPaster implements MouseListener, MouseMotionListener {

    static MPaster Instance() {
        if(_instance == null) {
            _instance = new MPaster();
            Presentor.Instance().addMouseListener(_instance);
            Presentor.Instance().addMouseMotionListener(_instance);
        }
        return _instance;
    }

    void reset() {
        _mouseDown = false;
        _cursor = Cursor.DEFAULT_CURSOR;
        _downX = 0;
        _downY = 0;
        _presentor.setCursor(Cursors._defaultCursor);
    }

    RectSelection getSelection() { return _selection; }

    BufferedImage getPastingImage() { return _pastingImage; }

    void startPaste(BufferedImage img) {
        int width = img.getWidth(null);
        int height = img.getHeight(null);
        if(width > _implementor.getWidth() || height > _implementor.getHeight()) {
            // if pasting image is bigger than current image
            // increase the current image size
            int newWidth = Math.max(width, _implementor.getWidth());
            int newHeight = Math.max(height, _implementor.getHeight());
            _implementor.resize(newWidth, newHeight, false);
        }
        double rate = _presentor.getZoomRate();
        width = (int)(width * rate);
        height = (int)(height * rate);
        _pastingImage = img;
        _selection = new RectSelection();
        _selection.setPoint(0, 0);
        _selection.setDimension(width - 1, height - 1);
        _selection.startDrawBorder();
    }

    void endPaste() {
        _implementor.backup();
        BufferedImage img = _implementor.getImage();
        Graphics g = img.createGraphics();
        RectSelection.Area area = _selection.getImageArea();
        g.drawImage(_pastingImage, area._x, area._y, area._width, area._height, null);
        g.dispose();
        _selection.destroy();
        _selection = null;
        _presentor.setMouseMode(Presentor.MOUSE_MODES.DRAGGING);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        if(_presentor.getMouseMode() != Presentor.MOUSE_MODES.PASTING)
            return;
        endPaste();
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if(_presentor.getMouseMode() != Presentor.MOUSE_MODES.PASTING)
            return;
        if(_cursor == Cursor.MOVE_CURSOR) {
            _mouseDown = true;
            _downX = e.getX();
            _downY = e.getY();
        } else {
            endPaste();
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if(_presentor.getMouseMode() != Presentor.MOUSE_MODES.PASTING)
            return;
        reset();
    }

    @Override
    public void mouseEntered(MouseEvent e) { }

    @Override
    public void mouseExited(MouseEvent e) { }

    @Override
    public void mouseDragged(MouseEvent e) {
        if(_presentor.getMouseMode() != Presentor.MOUSE_MODES.PASTING)
            return;
        if(!_mouseDown)
            return;
        Dimension max = _presentor.getPreferredSize();
        int deltaX = e.getX() - _downX;
        int deltaY = e.getY() - _downY;
        _downX = e.getX();
        _downY = e.getY();
        RectSelection.Area area = _selection.getScreenArea();
        int x0 = area._x;
        int y0 = area._y;
        area._x += deltaX;
        if(area._x < 0) area._x = 0;
        if(area._x + area._width > max.width) area._x = max.width - area._width;
        area._y += deltaY;
        if(area._y < 0) area._y = 0;
        if(area._y + area._height > max.height) area._y = max.height - area._height;
        _presentor.repaint(0, x0, y0, area._width + 1, area._height + 1);
        _presentor.repaint(0, area._x, area._y, area._width + 1, area._height + 1);
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        if(_presentor.getMouseMode() != Presentor.MOUSE_MODES.PASTING)
            return;
        if(_mouseDown)
            return;
        int x = e.getX();
        int y = e.getY();
        RectSelection.Area area = _selection.getScreenArea();
        if(x > area._x && x < area._x + area._width &&
           y > area._y && y < area._y + area._height) {
            _cursor = Cursor.MOVE_CURSOR;
            _presentor.setCursor(Cursors._moveCursor);
        } else {
            _cursor = Cursor.DEFAULT_CURSOR;
            _presentor.setCursor(Cursors._defaultCursor);
        }
    }

    private MPaster() {
        _presentor = Presentor.Instance();
        _implementor = Implementor.Instance();
    }

    private static MPaster      _instance = null;
    private Presentor               _presentor = null;
    private Implementor             _implementor = null;
    private int                     _cursor = Cursor.DEFAULT_CURSOR;
    private boolean                 _mouseDown = false;
    private int                     _downX = 0;
    private int                     _downY = 0;
    private RectSelection           _selection = null;
    private BufferedImage           _pastingImage = null;
}
